package edu.fim.core.service.impl;

import java.sql.SQLException;
import java.util.List;
import java.util.ResourceBundle;

import edu.fim.core.exception.BmiOutOfRangeException;
import edu.fim.core.exception.CaloriesThresholdExceededException;
import edu.fim.core.service.ConsumerService;
import edu.fim.core.util.BmiCategories;
import edu.fim.data.dao.ConsumerDAO;
import edu.fim.data.dao.DAO;
import edu.fim.data.dao.factory.DAOFactory;
import edu.fim.presentation.model.bean.Consumer;
import edu.fim.presentation.model.bean.Food;


public class ConsumerServiceImpl implements ConsumerService {

	private static ResourceBundle bundle = ResourceBundle.getBundle("ConsumerSQL");

	public void insert(Consumer consumer) {
		// TODO insert
	}
	
	public Consumer findById(Integer id) throws SQLException {
		String baseStatement = bundle.getString("consumer.findById");
		DAO<Consumer, Integer> consumerDAO = DAOFactory.getInstance().createConsumerDao();
		return consumerDAO.findById(baseStatement, id);
	}

	public List<Consumer> findAll() throws SQLException {
		DAO<Consumer, Integer> cd = DAOFactory.getInstance().createConsumerDao();
		return cd.findAll(bundle.getString("consumer.findAll"));
	}
	
	public Consumer findByUserAndPassword(String user, String password) throws SQLException {
		ConsumerDAO dao = DAOFactory.getInstance().createConsumerDao();
		return dao.findByUserAndPassword(bundle.getString("consumer.findByUserAndPassword"), user, password);
	}

	public void update(Consumer consumer) {
		// TODO update
	}

	public void delete(Consumer consumer) throws SQLException {
		String baseStatement = bundle.getString("consumer.delete");
		DAO<Consumer, Integer> consumerDAO = DAOFactory.getInstance().createConsumerDao();
		consumerDAO.delete(baseStatement, consumer);
	}
	
	public void setCaloriesThreshold(Consumer consumer, Double newThreshold) throws SQLException {
		String baseStatement = bundle.getString("consumer.update");
		ConsumerDAO consumerDAO = DAOFactory.getInstance().createConsumerDao();
		consumerDAO.update(baseStatement, consumer, newThreshold);
	}

	public void increaseCalories(Consumer consumer, Food food) throws CaloriesThresholdExceededException, SQLException {
		consumer.setCaloriasConsumidas(consumer.getCaloriasConsumidas() + food.getCalories());
		ConsumerDAO consumerDAO = DAOFactory.getInstance().createConsumerDao();
		consumerDAO.update(bundle.getString("consumer.updateConsumedCalories"), consumer, consumer.getCaloriasConsumidas());
		if (limiarExcedido(consumer)) {
			throw new CaloriesThresholdExceededException(
					consumer.getNome() + ", your calories threshold was exceeded.");
		}
	}

	public boolean limiarExcedido(Consumer consumer) {
		if (consumer.getCaloriasConsumidas() > consumer.getLimiarCalorias()) {
			return true;
		}
		return false;
	}

	public BmiCategories determineWeightSituation(Consumer consumer)
			throws BmiOutOfRangeException {
		Double bmiValue = calculateBmi(consumer);
		for (BmiCategories bmiCategory : BmiCategories.values()) {
			if (bmiCategory.hasValue(bmiValue)) {
				return bmiCategory;
			}
		}
		throw new BmiOutOfRangeException("The BMI is out of range.");
	}

	/**
	 * Auxiliary method that encapsulates the BMI formula.
	 * 
	 * @param consumer
	 * @return
	 * @throws ArithmeticException
	 */
	private Double calculateBmi(Consumer consumer) throws ArithmeticException {
		Double dividendo = (consumer.getAltura() * consumer.getAltura());
		if (dividendo.equals(0.0)) {
			throw new ArithmeticException("Division by zero!");
		}
		return consumer.getPeso() / dividendo;
	}
}